package com.utf8convert;

import info.monitorenter.cpdetector.io.*;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.util.ArrayList;

/**
 * Created by Coolcow on 2015/11/23 0023.
 */
public class Convert {
    public final static String DEFAULT_DIR = System.getProperty("user.dir");
    public static ArrayList<String> fileList = new ArrayList<>();

    public static void main(String[] args) {
        if (args != null && args.length >= 1) {
            for (String arg : args) {
                setFileList(arg);
            }
        } else {
            setFileList(DEFAULT_DIR);
        }

        for (String filename : fileList) {
            Path path = Paths.get(filename);
            try {
                convertToUtf8(path, "utf-8", StandardOpenOption.CREATE_NEW);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
//        System.out.println("fileList = " + fileList);

    }

    public static void setFileList(String pathname) {
        String FILTER_NAME = "java";
        File file = new File(pathname);
        if (file.isDirectory()) {
            File[] fs = file.listFiles();
            for (File element : fs != null ? fs : new File[0]) {
                setFileList(element.getPath());
            }
        } else {
            if (file.exists() && file.getName().endsWith(FILTER_NAME)) {
                fileList.add(file.getPath());
            }
        }

    }


    public static void convertToUtf8(Path path, String fileCharset, OpenOption... options) throws IOException {

        String charsetCode = getFileEncode(path);
        System.out.println("file CharSet = " + charsetCode);
        assert charsetCode != null;
        //老的BufferReader读取方式
        //BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path.toFile()),charsetCode));
        Charset oldCharset = Charset.forName(charsetCode);
        BufferedReader reader = Files.newBufferedReader(path, oldCharset);
        StringBuilder builder = new StringBuilder();
        while (true) {
            String line = reader.readLine();
            if (line == null) {
                if (builder.length() > 0) {
                    builder.deleteCharAt(builder.length() - 1);
                }
                break;
            }
            builder.append(line).append(System.getProperty("line.separator"));
        }
        //使用老的BufferedReader时关掉reader
        //reader.close();

        File backFile = new File(path.toString() + ".tmp_");
        Path backPath = Paths.get(backFile.getPath());
        deleteFile(backPath);

        //noinspection ResultOfMethodCallIgnored
        path.toFile().renameTo(backFile);


        Charset charset = Charset.forName(fileCharset);
        try (BufferedWriter writer = Files.newBufferedWriter(path, charset, options)) {
            writer.append(builder.toString());
            deleteFile(backPath);
            System.out.println("File Convert is Ok! [" + path.getFileName() + "]");
        } catch (Exception e) {

            e.printStackTrace();
            System.out.println("File write error! [name=" + path + "]");
            deleteFile(path);
            //noinspection ResultOfMethodCallIgnored
            backFile.renameTo(path.toFile());
        }

    }

    private static void deleteFile(Path path) throws IOException {
        if (Files.exists(path)) {
            Files.delete(path);
        }
    }


    /**
     * 使用开源包cpDetector获取文件编码格式
     * @param path  file path
     * @return      Charset String
     */
    public static String getFileEncode(Path path) {
        CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
        detector.add(UnicodeDetector.getInstance());
        detector.add(JChardetFacade.getInstance());
        detector.add(ASCIIDetector.getInstance());

        Charset charset = null;
        try {
            charset = detector.detectCodepage(path.toUri().toURL());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        if (charset != null)
            return charset.name();
        else
            return null;
    }


}
